package com.wmwu.mybatistest.handler;

import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.json.JSONObject;
import com.wmwu.mybatistest.annotations.DataCoverageDataAuth;
import com.wmwu.mybatistest.condition.DataAuthCondition;
import com.wmwu.mybatistest.utils.ExecutorPluginUtils;
import com.wmwu.mybatistest.utils.Tools;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.Invocation;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.ClassUtils;

import java.lang.reflect.Method;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

/**
 * @Description: TODO
 * @author: Mr.wu
 * @date: 2022年06月23日 18:21
 */
@Component
public class DataCoverageDataAuthHandler {
    Logger log = LogManager.getLogger(DataCoverageDataAuthHandler.class.getName());

    /**
     * 权限校验条件map
     */
    @Autowired
    private final Map<String, DataAuthCondition> conditionHashMap = new HashMap<>();

    public void resetSql2Invocation(Invocation invocation) throws SQLException {
        final Object[] args = invocation.getArgs();
        //获取注解信息,若mapper's 方法不存在注解则不进行sql拆解
        DataCoverageDataAuth dataCoverageDataAuth = findDataCoverageDataAuthAnnotation((MappedStatement) args[0]);
        if (dataCoverageDataAuth == null) {
            return;
        }
        //原生sql
        String processSql = ExecutorPluginUtils.getSqlByInvocation(invocation);
        log.error("schema替换前：{}", processSql);
        //获取spring注入bean对象
        DataAuthCondition dataAuthCondition = conditionHashMap.get(dataCoverageDataAuth.type().getFieldClassName());
        //获取替换的SQL
        String replaceSql = dataAuthCondition.resetSql(dataCoverageDataAuth, processSql);
        log.error("schema替换后：{}", replaceSql);
        //将替换的SQL回填到invocation
        ExecutorPluginUtils.resetSql2Invocation(invocation, replaceSql);
    }


    private DataCoverageDataAuth findDataCoverageDataAuthAnnotation(MappedStatement mappedStatement) {
        String id = mappedStatement.getId();
        String className = id.substring(0, id.lastIndexOf("."));
        String mapperBean = Tools.firstCharToLower(Tools.getShortName(className));
        Object mapper = SpringUtil.getBean(mapperBean);
        String methodName = id.substring(id.lastIndexOf(".") + 1);
        Class<?>[] interfaces = ClassUtils.getAllInterfaces(mapper);

        Class[] var6 = interfaces;
        int var7 = interfaces.length;
        for (int var8 = 0; var8 < var7; ++var8) {
            Class<?> mapperInterface = var6[var8];
            Method[] var10 = mapperInterface.getDeclaredMethods();
            int var11 = var10.length;
            for (int var12 = 0; var12 < var11; ++var12) {
                Method method = var10[var12];
                if (methodName.equals(method.getName()) && method.isAnnotationPresent(DataCoverageDataAuth.class)) {
                    return method.getAnnotation(DataCoverageDataAuth.class);
                }
            }
        }
        return null;
    }


    private String findMapperAnnotationClassName(MappedStatement mappedStatement) {
        String id = mappedStatement.getId();
        String className = id.substring(0, id.lastIndexOf("."));
        return Tools.firstCharToLower(Tools.getShortName(className));
    }


}
